﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GameLibrary.Map
{
    using Settlement;
    using Unit;
    [Serializable]
    public class RegionInfo:Region<SettlementInfo,UnitInfo>
    {
        #region constructor

        public RegionInfo(Position Start):base(Start)
        {
            Refresh(); // must be a visited region therefore should be refreshed.
        }

        public RegionInfo(RegionInfo region) : base(region) { }

        public RegionInfo(Region<Settlement, Unit> region)
            :base(region.Start)
        {
           foreach(var unit in region.GetUnits())
           {
               this.AddUnit(unit.Info);
           }
           foreach (var settlement in region.GetSettlements())
           {
               this.AddSettlement(settlement.Info);
           }
        }

        #endregion

        #region refresh

        public void Refresh()
        {
            GameMap map = GameMap.UniqueInstance;
            this.DeleteAll();
            foreach (var a in map.GetRegionSettlements(this.Start))
                this.AddSettlement(a.Info);
            foreach (var u in map.GetRegionUnits(this.Start))
                this.AddUnit(u.Info);
        }

        public void RefreshCity(Settlement city)
        {
            this.RemoveSettlement(city.ID);
            this.AddSettlement(city.Info);
        }

        public void RefreshUnit(Unit unit)
        {
            this.RemoveUnit(unit.ID);
            this.AddUnit(unit.Info);
        }

        #endregion

        #region add

        public override bool AddSettlement(SettlementInfo city)
        {
            if (this.ContainsSettlementID(city.ID) == true) // remove old infomation
                this.RemoveSettlement(city.ID);
            return base.AddSettlement(city);
        }

        public override bool AddUnit(UnitInfo unit)
        {
            if (this.ContainsUnitID(unit.ID) == true) // remove old info
                this.RemoveUnit(unit.ID);
            return base.AddUnit(unit);
        }

        #endregion

        #region get move cost map

        /// <summary>
        /// return move cost by calculate tile.movecost/roadlevel
        /// if provide playerID
        /// return move cost by add additional check whether settlement belong to playerid
        /// if not belong to player with playerid the move cost of this point equals +inf.
        /// </summary>
        /// <param name="playerID"></param>
        /// <returns></returns>
        public double[,] GetMoveCostMap(uint playerID = 0)
        {
            double[,] costmap = new double[GMHelper.Width,GMHelper.Height];

            for (int i = 0; i < GMHelper.Width; i++)
                for (int j = 0; j < GMHelper.Height; j++)
                {
                    Settlement city = GameMap.UniqueInstance.GetSettlementByPosition(this.Start + new Position(i, j));
                    if (playerID != 0)
                    {
                        var unit = GameMap.UniqueInstance.GetUnitsByPosition(this.Start + new Position(i, j));
                        if (unit != null
                            && unit.First().OwnerID != playerID)
                        {
                            costmap[i, j] = double.PositiveInfinity;

                            continue;
                        }
                    }

                    double roadLevel = 1.0;
                    if (city != null)
                        roadLevel += city.GetBuildingLevel(SettlementHelper.Road);
                    costmap[i, j] = TileMap.UniqueInstance[i + this.Start.X, j + this.Start.Y].BaseMoveCost
                        / roadLevel;

                }
            return costmap;
        }

        #endregion
    }
}
